#include <iostream>
#include "minestrategy.h"

MineStrategy::MineStrategy() {
    std::cout<<"运行MinStrategy"<<std::endl;
}

/*
 * 分钟级别量化
 *
 * 存储当前K线及前两帧K线数据到queue中
 *
 * 必须是分钟级别数据
 *
 *
 *
 */

void MineStrategy::onCandle(const CandleData &candle)
{
    if(m_data.size()==1||m_data.size()==0){
        m_data.emplace_back(candle);
    }else if(m_data.size()==2){
        //当当前数据队列中数据量是三的时候才会进行操作
        //当前队列中存储前两帧的数据m_data
        CandleData start=m_data.front();  //第一帧数据
        CandleData end=m_data.back();     //最后一帧数据，即当前帧的数据

        /*************************************************************核心逻辑************************************************************************/

        //如果当前价格大于第一帧K线的开盘价和收盘价 并且当前价格大于第二帧价格的开盘价则  作为开仓的第一层条件
        if(candle.open>start.open&&candle.open>start.close&&candle.open>end.open&&m_holdings==0){ //&&candle.open>start.high

            //买入触发

            //如果当前持仓为0，始终保持只有一笔持仓
            if(m_holdings==0){
                m_lastPrice=candle.open;

                buy(candle,m_balance / candle.close * 0.9);  //100$ / 10=10$

                //记录交易信息
                //当买入之后，将当前帧数据插入
                m_data.emplace_back(candle);  //将K线数据存储到m_data中
                //买入之后，将第一帧数据删除
                m_data.pop_front();

            }

        }
        //卖出逻辑 如果当前开盘价格涨幅度大于1%  则卖出全部份额
        else if(candle.open>m_lastPrice*1.01){
            if (m_holdings > 0) {
                sell(candle); // 卖出所有持仓
                //记录持仓详情
            }
            m_data.pop_front();
            m_data.emplace_back(candle);
            std::cout<<"deque size:"<<m_data.size()<<std::endl;
        }else if(candle.open<m_lastPrice*0.99&&m_holdings==1){
            //进行风险管理,若低于某个比例，马上止损
            sell(candle);
        }else{
            //如果不满足当前开单条件，则删除第一帧数据，并且添加当前数据到队列中去
            m_data.pop_front();
            m_data.emplace_back(candle);
            std::cout<<"deque size:"<<m_data.size()<<std::endl;
        }
    }
    std::cout<<"end mine strategy"<<std::endl;
}



/*******************************************重构输入输出 添加交易费率*********************************************************/
void MineStrategy::buy(const CandleData &candle, double amount)
{
    std::cout<<"买入 资金费率为："<<m_fee<<std::endl;
    if (amount <= 0 || m_balance <= 0) return;

    m_lastPrice = candle.close;

    //此处进行修改，将原先的收盘价改为开盘价  并计算资金费率
    double totalCost = amount * candle.open+amount*candle.open*m_fee; //开盘价 *数量+开盘价*数量*资金费率
    if (totalCost > m_balance) {
        amount = m_balance / candle.close;
        totalCost = m_balance;
    }

    m_balance -= totalCost;
    m_holdings += amount;

    TradeRecord trade;
    trade.type = TradeRecord::BUY;
    trade.timestamp = candle.timestamp;
    trade.price = candle.close;
    trade.amount = amount;
    trade.total = totalCost;
    trade.balance = getFinalBalance();
    trade.profit = trade.balance - m_initialBalance;

    m_trades.append(trade);

}

void MineStrategy::sell(const CandleData &candle, double amount)
{
     std::cout<<"卖出 资金费率为："<<m_fee<<std::endl;
    if (m_holdings <= 0) return;

    m_lastPrice = candle.close;
    double sellAmount = (amount <= 0) ? m_holdings : qMin(amount, m_holdings);
    double totalRevenue = sellAmount * candle.open-sellAmount*candle.open*m_fee;               //此处由开盘价计算得来，因此按照开盘价进行卖出

    m_holdings -= sellAmount;
    m_balance += totalRevenue;

    TradeRecord trade;
    trade.type = TradeRecord::SELL;
    trade.timestamp = candle.timestamp;
    trade.price = candle.close;
    trade.amount = sellAmount;
    trade.total = totalRevenue;
    trade.balance = getFinalBalance();
    trade.profit = trade.balance - m_initialBalance;

    m_trades.append(trade);
}
